package com.zhiyou.app.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.math.MathUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.xinchao.component.multids.util.PageInfoUtil;
import com.zhiyou.app.common.constant.UserHandler;
import com.zhiyou.app.common.exception.BizException;
import com.zhiyou.app.common.util.GenerateNumUtil;
import com.zhiyou.app.common.util.ObjSorterUtil;
import com.zhiyou.app.config.oss.OssUtil;
import com.zhiyou.app.mapper.OrderMapper;
import com.zhiyou.app.pojo.bo.PayAmountCalcResultBo;
import com.zhiyou.app.pojo.bo.PrePayCrateResult;
import com.zhiyou.app.pojo.entity.*;
import com.zhiyou.app.pojo.enums.*;
import com.zhiyou.app.pojo.vo.*;
import com.zhiyou.app.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author jonathan.z
 * @since 2025-07-03
 */
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderEntity> implements IOrderService {
    @Resource
    private IOrderService orderService;
    @Resource
    private IGoodsService goodsService;
    @Resource
    private IOrderGoodsService orderGoodsService;
    @Resource
    private WxPayService wxPayService;
    @Resource
    private IUserService userService;
    @Resource
    private ITaskService taskService;
    @Resource
    private IWechatRefundHistoryService wechatRefundHistoryService;
    @Resource
    private IWechatPayHistoryService wechatPayHistoryService;
    @Resource
    private IUserWalletService userWalletService;
    @Resource
    private IWalletHistoryService walletHistoryService;
    @Resource
    private IIdGiftRuleService idGiftRuleService;
    @Resource
    private IIdAddonRuleService idAddonRuleService;
    @Value("${wx.pay.notifyUrl}")
    private String notifyUrl;
    /**
     * 分佣比例
     */
    @Value("${invitation.Distribute.percentage:0.2}")
    private String invitationDistributePercentage;

    @PostConstruct
    private void init() {
        log.info("OrderServiceImpl init");
        wxPayService.getConfig().setNotifyUrl(notifyUrl);
    }

    private PayAmountCalcResultBo calcPayAmount(List<String> submitForPayGoodsCodes, List<GoodsEntity> goods, List<OrderGoodsEntity> orderGoodsEntities) {
        PayAmountCalcResultBo payAmountCalcResultBo = new PayAmountCalcResultBo();
        Map<Integer, List<OrderGoodsEntity>> orderGoodsPaidMapping = orderGoodsEntities.stream().collect(Collectors.groupingBy(OrderGoodsEntity::getPaid));
        boolean allPaid = orderGoodsPaidMapping.containsKey(1) && !orderGoodsPaidMapping.containsKey(0);
        boolean partPaid = orderGoodsPaidMapping.containsKey(1) && orderGoodsPaidMapping.containsKey(0);
        boolean nonePaid = !allPaid && !partPaid;
        List<IdGiftRuleEntity> giftRuleEntities = idGiftRuleService.list(new LambdaQueryWrapper<IdGiftRuleEntity>().in(IdGiftRuleEntity::getTriggerGoodsCode, submitForPayGoodsCodes));
        List<String> hasPaidGoodsList = orderGoodsEntities.stream().filter(t -> t.getPaid() == 1).map(OrderGoodsEntity::getGoodsCode).collect(Collectors.toList());
        if (submitForPayGoodsCodes.stream().anyMatch(hasPaidGoodsList::contains)) {
            throw new BizException("支付商品中存在已支付商品请勿重复支付");
        }
        List<IdAddonRuleEntity> addonRuleEntities = hasPaidGoodsList.isEmpty() ? new ArrayList<>() : idAddonRuleService.list(new LambdaQueryWrapper<IdAddonRuleEntity>().in(IdAddonRuleEntity::getTriggerGoodsCode, hasPaidGoodsList));
        if (allPaid) {
            throw new BizException("订单已全部支付，请勿重复支付");
        } else if (nonePaid) {
            if (!giftRuleEntities.isEmpty()) {
                List<String> giftGoodsCodes = giftRuleEntities.stream().map(IdGiftRuleEntity::getGiftGoodsCode).collect(Collectors.toList());
                List<GoodsEntity> giftGoods = goodsService.list(new LambdaQueryWrapper<GoodsEntity>().in(GoodsEntity::getGoodsCode, giftGoodsCodes));
                submitForPayGoodsCodes.removeAll(giftGoodsCodes);
                if (submitForPayGoodsCodes.isEmpty()) {
                    throw new BizException("存在商品互为礼品，支付商品不存在");
                } else {
                    goods.addAll(giftGoods);
                }
            }
            payAmountCalcResultBo.setPayGoods(goods);
            payAmountCalcResultBo.setPayAmount(goods.stream().filter(t -> submitForPayGoodsCodes.contains(t.getGoodsCode())).mapToInt(GoodsEntity::getAmount).sum());
        } else {
            // 部分支付
            Map<String, IdAddonRuleEntity> addonGoodsCodeEntityList = addonRuleEntities.stream().filter(t -> submitForPayGoodsCodes.contains(t.getAddonGoodsCode())).collect(Collectors.toMap(IdAddonRuleEntity::getAddonGoodsCode, t -> t));
            if (addonGoodsCodeEntityList.isEmpty()) {
                payAmountCalcResultBo.setPayAmount(goods.stream().filter(t -> submitForPayGoodsCodes.contains(t.getGoodsCode())).mapToInt(GoodsEntity::getAmount).sum());
            } else {
                payAmountCalcResultBo.setPayAmount(goods.stream().map(t -> addonGoodsCodeEntityList.containsKey(t.getGoodsCode()) ? addonGoodsCodeEntityList.get(t.getGoodsCode()).getAddonPrice() : t.getAmount())
                        .mapToInt(t -> t).sum());
            }
            payAmountCalcResultBo.setPayGoods(goods);
        }
        return payAmountCalcResultBo;

    }


    @Override
    public PrePayCrateResult createPreOrder(PreOrder4PayRequestVo preOrder4PayRequestVo) {
        OrderEntity orderEntity = preOrder4PayRequestVo.getOrder();
        List<GoodsEntity> goodsEntityList = goodsService.list(new LambdaQueryWrapper<GoodsEntity>().in(GoodsEntity::getGoodsCode, preOrder4PayRequestVo.getGoodsCode()));
        List<OrderGoodsEntity> orderGoodsEntities = orderGoodsService.list(new LambdaQueryWrapper<OrderGoodsEntity>().eq(OrderGoodsEntity::getOrderNum, orderEntity.getOrderNum()));
        PayAmountCalcResultBo payAmountCalcResultBo = calcPayAmount(preOrder4PayRequestVo.getGoodsCode(), goodsEntityList, orderGoodsEntities);
        if (!Objects.equals(preOrder4PayRequestVo.getPayAmount(), payAmountCalcResultBo.getPayAmount())) {
            throw new BizException("支付金额不正确");
        }
        UserEntity byId = userService.getById(UserHandler.getLoginUser().getUserId());
        WxPayUnifiedOrderV3Request wxPayUnifiedOrderV3Request = new WxPayUnifiedOrderV3Request();
        wxPayUnifiedOrderV3Request.setAppid(wxPayService.getConfig().getAppId());
        wxPayUnifiedOrderV3Request.setMchid(wxPayService.getConfig().getMchId());
        wxPayUnifiedOrderV3Request.setDescription("订单：" + orderEntity.getOrderNum() + "支付:" + payAmountCalcResultBo.getPayGoods().stream().map(GoodsEntity::getGoodsName).collect(Collectors.joining(",")));
        wxPayUnifiedOrderV3Request.setOutTradeNo(String.format("%s-%s", orderEntity.getOrderNum(),
                payAmountCalcResultBo.getPayGoods().stream().map(t -> t.getId().toString()).sorted().collect(Collectors.joining("-"))));
        wxPayUnifiedOrderV3Request.setNotifyUrl(wxPayService.getConfig().getNotifyUrl());
        wxPayUnifiedOrderV3Request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(payAmountCalcResultBo.getPayAmount()));
        wxPayUnifiedOrderV3Request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(byId.getOpenId()));
        wxPayUnifiedOrderV3Request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(preOrder4PayRequestVo.getClientIP()));
        wxPayUnifiedOrderV3Request.setSettleInfo(new WxPayUnifiedOrderV3Request.SettleInfo().setProfitSharing(false));
        wxPayUnifiedOrderV3Request.setSupportFapiao(true);
        wxPayUnifiedOrderV3Request.setGoodsTag(payAmountCalcResultBo.getPayGoods().stream().map(GoodsEntity::getGoodsCode).collect(Collectors.joining(",")));
        wxPayUnifiedOrderV3Request.setTimeExpire(DateUtil.format(DateUtil.offsetHour(new Date(), 2), "yyyy-MM-dd'T'HH:mm:ssXXX"));
        wxPayUnifiedOrderV3Request.setAttach("支付订单:[" + orderEntity.getOrderNum() + "]费用");
        WxPayUnifiedOrderV3Result.JsapiResult orderV3;
        try {
            orderV3 = wxPayService.createOrderV3(TradeTypeEnum.JSAPI, wxPayUnifiedOrderV3Request);
        } catch (WxPayException e) {
            log.error("微信预订单创建失败", e);
            throw new BizException("微信预订单创建失败");
        }
        return new PrePayCrateResult(orderV3, wxPayUnifiedOrderV3Request.getOutTradeNo(), payAmountCalcResultBo.getPayAmount());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public CreateOrderResponseVo createOrder(OrderCreateRequestVo orderCreateRequestVo) {
        CreateOrderResponseVo createOrderResponse = new CreateOrderResponseVo();
        if (orderCreateRequestVo.getGoodsCodes() != null && !orderCreateRequestVo.getGoodsCodes().isEmpty()) {
            OrderEntity orderEntity;
            List<GoodsEntity> goods = goodsService.list(new LambdaQueryWrapper<GoodsEntity>().in(GoodsEntity::getGoodsCode, orderCreateRequestVo.getGoodsCodes()));
            // 按给定商品编码排序
            goods = ObjSorterUtil.sortByOrder(goods, orderCreateRequestVo.getGoodsCodes(), GoodsEntity::getGoodsCode);
            orderEntity = doCreateOrder(goods, orderCreateRequestVo.getBindParam());
            List<OrderGoodsEntity> orderGoods = new ArrayList<>();
            goods.forEach(goodsEntity -> orderGoods.add(new OrderGoodsEntity().setOrderNum(orderEntity.getOrderNum())
                    .setGoodsId(goodsEntity.getId())
                    .setGoodsCode(goodsEntity.getGoodsCode())
                    .setUserId(UserHandler.getLoginUser().getUserId())
                    .setGoodsCount(1)));
            if (goods.size() < orderGoods.size()) {
                throw new BizException("订单中部分商品不存在");
            }
            try {
                if (!orderGoods.isEmpty()) {
                    orderGoodsService.saveBatch(orderGoods);
                }
                orderService.save(orderEntity);
            } catch (Exception ex) {
                log.error("保存订单失败", ex);
                throw new BizException("保存订单失败", ex.getMessage());
            }
            OrderQueryRequestVo orderQueryRequestVo = new OrderQueryRequestVo();
            orderQueryRequestVo.setPageNum(1);
            orderQueryRequestVo.setPageSize(10);
            createOrderResponse.setOrderInfo(queryOrder(orderQueryRequestVo.setOrderNum(orderEntity.getOrderNum())).getList().get(0));
            return createOrderResponse;
        } else {
            throw new BizException("订单中不存在商品");
        }
    }

    private OrderEntity doCreateOrder(List<GoodsEntity> goods, Map<String, Object> bindParam) {
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setOrderNum(GenerateNumUtil.generateNum(NumTypeEnum.ORD));
        orderEntity.setUserId(UserHandler.getLoginUser().getUserId());
        orderEntity.setOrderAmount(0);
        if (bindParam != null && !bindParam.isEmpty()) {
            orderEntity.setOrderParam(JSONUtil.toJsonStr(bindParam));
        }
        orderEntity.setOrderStatus(OrderStatusEnum.CREATED);
        orderEntity.setOrderDesc(goods.stream().map(GoodsEntity::getGoodsName).collect(Collectors.joining(",")));
        return orderEntity;
    }

    @Override
    public PageInfo<OrderQueryResponseVo> queryOrder(OrderQueryRequestVo orderQueryRequestVo) {
        PageMethod.startPage(orderQueryRequestVo.getPageNum(), orderQueryRequestVo.getPageSize());
        LambdaQueryWrapper<OrderEntity> queryWrapper = new LambdaQueryWrapper<>();
        if (UserHandler.getLoginUser().getUserId() != 0) {
            queryWrapper.eq(OrderEntity::getUserId, UserHandler.getLoginUser().getUserId());
        }
        if (orderQueryRequestVo.getStartDate() != null) {
            queryWrapper.ge(OrderEntity::getCreateTime, orderQueryRequestVo.getStartDate());
        }
        if (orderQueryRequestVo.getEndDate() != null) {
            queryWrapper.le(OrderEntity::getCreateTime, DateUtil.offsetDay(orderQueryRequestVo.getEndDate(), 1));
        }
        if (StringUtils.isNotBlank(orderQueryRequestVo.getContent())) {
            queryWrapper.like(OrderEntity::getOrderDesc, orderQueryRequestVo.getContent());
        }
        if (orderQueryRequestVo.getOrderStatus() != null) {
            queryWrapper.eq(OrderEntity::getOrderStatus, orderQueryRequestVo.getOrderStatus().getCode());
        }
        if (orderQueryRequestVo.getOrderNum() != null) {
            queryWrapper.eq(OrderEntity::getOrderNum, orderQueryRequestVo.getOrderNum());
        }
        Page<OrderEntity> pageInfo = (Page<OrderEntity>) list(queryWrapper.orderByDesc(OrderEntity::getCreateTime));
        List<OrderQueryResponseVo> collect = pageInfo.getResult().stream().map(t -> {
            OrderQueryResponseVo orderQueryResponseVo = new OrderQueryResponseVo();
            return getOrderQueryResponseVo(t, orderQueryResponseVo, false);
        }).collect(Collectors.toList());
        return PageInfoUtil.build(pageInfo, collect);
    }

    private OrderQueryResponseVo getOrderQueryResponseVo(OrderEntity t, OrderQueryResponseVo orderQueryResponseVo, boolean detail) {
        List<OrderGoodsItem> goodsItem = orderGoodsService.list(new LambdaQueryWrapper<OrderGoodsEntity>().eq(OrderGoodsEntity::getOrderNum, t.getOrderNum()))
                .stream().map(orderGoodsEntity -> {
                    OrderGoodsItem orderGoodsItem = new OrderGoodsItem();
                    GoodsEntity goods = goodsService.getById(orderGoodsEntity.getGoodsId());
                    orderGoodsItem.setGoodsCode(goods.getGoodsCode())
                            .setGoodsCount(orderGoodsEntity.getGoodsCount())
                            .setGoodsDesc(goods.getDescrption())
                            .setGoodsId(orderGoodsEntity.getGoodsId())
                            .setGoodsPhoto(goods.getImage())
                            .setGoodsPrice(goods.getAmount())
                            .setPaid(orderGoodsEntity.getPaid())
                            .setGoodsName(goods.getGoodsName());
                    return orderGoodsItem;
                }).collect(Collectors.toList());
        if (goodsItem.isEmpty()) {
            return null;
        }
        List<String> orderParam = null;
        if (t.getOrderParam() != null) {
            orderParam = JSONUtil.toBean(t.getOrderParam(), new TypeReference<List<String>>() {
                @Override
                public Type getType() {
                    return super.getType();
                }
            }, true);
        }
        orderQueryResponseVo.setOrderNum(t.getOrderNum())
                .setOrderAmount(t.getOrderAmount())
                .setOrderDesc(t.getOrderDesc())
                .setCreatedTime(t.getCreateTime())
                .setOrderStatus(t.getOrderStatus())
                .setOrderImage(getOrderImg(goodsItem, orderParam))
                .setOrderGoods(goodsItem);
        if (detail) {
            orderQueryResponseVo.setTaskInfos(taskService.list(new LambdaQueryWrapper<TaskEntity>().eq(TaskEntity::getOrderNum, t.getOrderNum()).orderByDesc(TaskEntity::getCreateTime)));
            List<WechatRefundHistoryEntity> refundHistoryEntities = wechatRefundHistoryService.list(new LambdaQueryWrapper<WechatRefundHistoryEntity>().eq(WechatRefundHistoryEntity::getOrderNum, t.getOrderNum()));
            List<RefundListDetailVo> collect = refundHistoryEntities.stream().map(u -> {
                RefundListDetailVo refundListDetailVo = new RefundListDetailVo();
                BeanUtil.copyProperties(u, refundListDetailVo);
                refundListDetailVo.setUserInfo(userService.getProfile(u.getUserId()));
                return refundListDetailVo;
            }).collect(Collectors.toList());
            orderQueryResponseVo.setRefundInfos(collect);
            List<WechatPayHistoryEntity> list = wechatPayHistoryService.list(new LambdaQueryWrapper<WechatPayHistoryEntity>().eq(WechatPayHistoryEntity::getContent, "支付订单:[" + t.getOrderNum() + "]费用"));
            if (!list.isEmpty()) {
                orderQueryResponseVo.setPaidInfo(list.get(0));
            }
        }
        return orderQueryResponseVo;
    }

    private String getOrderImg(List<OrderGoodsItem> goodsItems, List<String> orderParam) {
        if (orderParam != null && !orderParam.isEmpty()) {
            List<String> images = orderParam.stream().filter(this::isImage).collect(Collectors.toList());
            if (images.isEmpty()) {
                return goodsItems.get(0).getGoodsPhoto();
            } else {
                return images.get(0).replace("photoUrl=", "");
            }
        } else {
            return goodsItems.get(0).getGoodsPhoto();
        }
    }

    private boolean isImage(String img) {
        String suffix = img.substring(img.lastIndexOf(".") + 1).toLowerCase();
        return Stream.of("png", "jpg", "gif", "jpeg", "bmp").anyMatch(suffix::startsWith);
    }

    @Transactional
    @Override
    public Boolean handleRefund(HandleRefundRequestVo handleRefundRequestVo) {
        WechatRefundHistoryEntity wechatRefundHistory = wechatRefundHistoryService.getOne(new LambdaQueryWrapper<WechatRefundHistoryEntity>().eq(WechatRefundHistoryEntity::getOutRefundNum, handleRefundRequestVo.getRefundNum()));
        if (wechatRefundHistory == null) {
            throw new BizException("退款记录不存在");
        }
        OrderEntity orderEntity = orderService.getOne(new LambdaQueryWrapper<OrderEntity>().eq(OrderEntity::getOrderNum, wechatRefundHistory.getOrderNum()));
        if (handleRefundRequestVo.getAccept() == 1) {
            orderEntity.setOrderStatus(OrderStatusEnum.REFUND);
            orderService.updateById(orderEntity);
        } else {
            orderEntity.setOrderStatus(OrderStatusEnum.REJECT_REFUND);
            orderEntity.setOrderDesc("订单退款被拒绝");
            orderService.updateById(orderEntity);
            wechatRefundHistory.setStatus(RefundStatusEnum.CLOSE);
            wechatRefundHistoryService.updateById(wechatRefundHistory);
            return false;
        }
        WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount().setTotal(orderEntity.getOrderAmount())
                .setRefund(wechatRefundHistory.getAmount()).setCurrency("CNY");
        try {
            WxPayRefundV3Result result = wxPayService.refundV3(new WxPayRefundV3Request().setAmount(amount)
                    .setNotifyUrl(notifyUrl)
                    .setOutRefundNo(wechatRefundHistory.getOutRefundNum())
                    .setReason("退款")
                    .setSubMchid(wxPayService.getConfig().getSubMchId())
                    .setTransactionId(orderEntity.getWxTransactionId()));
            switch (result.getStatus()) {
                case "PROCESSING":
                    wechatRefundHistory.setStatus(RefundStatusEnum.PROCESSING);
                    break;
                case "ABNORMAL":
                    wechatRefundHistory.setStatus(RefundStatusEnum.ABNORMAL);
                    break;
                case "SUCCESS":
                    wechatRefundHistory.setStatus(RefundStatusEnum.SUCCESS);
                    break;
            }
            wechatRefundHistoryService.updateById(wechatRefundHistory);
        } catch (WxPayException e) {
            throw new BizException("微信退款失败", e.getReturnMsg());
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean userRefundOrder(UserRefundOrderRequestVo userRefundOrderRequestVo) {
        OrderEntity orderEntity = getOne(new LambdaQueryWrapper<OrderEntity>().eq(OrderEntity::getOrderNum, userRefundOrderRequestVo.getOrderNum()));
        if (orderEntity == null) {
            throw new BizException("订单不存在");
        } else if (orderEntity.getOrderAmount() == 0) {
            throw new BizException("订单金额为0，不支持退款");
        } else if (orderEntity.getOrderStatus() != OrderStatusEnum.FINISHED) {
            throw new BizException("订单状态不支持退款");
        }
        WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount().setTotal(orderEntity.getOrderAmount())
                .setRefund(orderEntity.getOrderAmount()).setCurrency("CNY");
        if (orderEntity.getOrderAmount() < userRefundOrderRequestVo.getRefundAmount()) {
            throw new BizException("退款金额大于订单金额");
        }
        String refNum = GenerateNumUtil.generateNum(NumTypeEnum.REF);
        WechatRefundHistoryEntity wechatRefundHistoryEntity = new WechatRefundHistoryEntity()
                .setAmount(amount.getRefund())
                .setOrderNum(userRefundOrderRequestVo.getOrderNum())
                .setUserId(UserHandler.getLoginUser().getUserId())
                .setContent(userRefundOrderRequestVo.getRefundReason())
                .setStatus(RefundStatusEnum.CREATE)
                .setOutRefundNum(refNum);
        wechatRefundHistoryService.save(wechatRefundHistoryEntity);
        orderEntity.setOrderStatus(OrderStatusEnum.REFUND_APPLY);
        updateById(orderEntity);
        return true;
    }

    @Override
    public PageInfo<RefundListDetailVo> queryRefundList(RefundListQueryRequestVo refundListQueryRequestVo) {
        PageMethod.startPage(refundListQueryRequestVo.getPageNum(), refundListQueryRequestVo.getPageSize());
        LambdaQueryWrapper<WechatRefundHistoryEntity> wechatRefundHistoryEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (refundListQueryRequestVo.getOrderNum() != null) {
            wechatRefundHistoryEntityLambdaQueryWrapper.eq(WechatRefundHistoryEntity::getOrderNum, refundListQueryRequestVo.getOrderNum());
        }
        if (refundListQueryRequestVo.getRefundNum() != null) {
            wechatRefundHistoryEntityLambdaQueryWrapper.eq(WechatRefundHistoryEntity::getOutRefundNum, refundListQueryRequestVo.getRefundNum());
        }
        if (refundListQueryRequestVo.getRefundStatus() != null) {
            wechatRefundHistoryEntityLambdaQueryWrapper.eq(WechatRefundHistoryEntity::getStatus, refundListQueryRequestVo.getRefundStatus());
        }
        if (refundListQueryRequestVo.getStartDate() != null) {
            wechatRefundHistoryEntityLambdaQueryWrapper.ge(WechatRefundHistoryEntity::getCreateTime, refundListQueryRequestVo.getStartDate());
        }
        if (refundListQueryRequestVo.getEndDate() != null) {
            wechatRefundHistoryEntityLambdaQueryWrapper.le(WechatRefundHistoryEntity::getCreateTime, refundListQueryRequestVo.getEndDate());
        }
        Page<WechatRefundHistoryEntity> refundHistoryEntities = (Page<WechatRefundHistoryEntity>) wechatRefundHistoryService.list(wechatRefundHistoryEntityLambdaQueryWrapper);
        List<RefundListDetailVo> collect = refundHistoryEntities.stream().map(t -> {
            RefundListDetailVo refundListDetailVo = new RefundListDetailVo();
            BeanUtil.copyProperties(t, refundListDetailVo);
            refundListDetailVo.setUserInfo(userService.getProfile(t.getUserId()));
            return refundListDetailVo;
        }).collect(Collectors.toList());
        return PageInfoUtil.build(refundHistoryEntities, collect);
    }

    @Override
    public OrderQueryResponseVo orderDetail(String orderNum) {
        OrderEntity orderEntity = getOne(new LambdaQueryWrapper<OrderEntity>().eq(OrderEntity::getOrderNum, orderNum));
        return getOrderQueryResponseVo(orderEntity, new OrderQueryResponseVo(), true);
    }

    @Override
    public void completeOrder(OrderEntity orderEntity) {
        orderEntity.setOrderStatus(OrderStatusEnum.COMPLETE);
        updateById(orderEntity);
        log.info("订单完成，订单号：{}, 开始分佣...", orderEntity.getOrderNum());
        distributeInvitation(orderEntity.getOrderAmount(), orderEntity.getUserId());
    }

    @Override
    public List<OrderGoodsItem> queryOrderGoodInfoResponseVo(String orderNum) {
        OrderQueryResponseVo orderQueryResponseVo = orderDetail(orderNum);
        //按照付费状态分类
        Map<Integer, List<String>> paidGoodsCodeMapping = orderQueryResponseVo.getOrderGoods().stream().collect(Collectors.groupingBy(OrderGoodsItem::getPaid, Collectors.mapping(OrderGoodsItem::getGoodsCode, Collectors.toList())));
        //查询可能加赠
        Map<String, List<IdGiftRuleEntity>> giftRulesMapping = paidGoodsCodeMapping.containsKey(0) ? idGiftRuleService.list(new LambdaQueryWrapper<IdGiftRuleEntity>().in(IdGiftRuleEntity::getTriggerGoodsCode, paidGoodsCodeMapping.get(0))).stream().collect(Collectors.groupingBy(IdGiftRuleEntity::getTriggerGoodsCode)):new HashMap<>();
        // 查询实际加价金额，用于修改支付金额
        Map<String, List<IdAddonRuleEntity>> realAddOn = paidGoodsCodeMapping.containsKey(1) ? idAddonRuleService.list(new LambdaQueryWrapper<IdAddonRuleEntity>().in(IdAddonRuleEntity::getTriggerGoodsCode, paidGoodsCodeMapping.get(1))).stream().collect(Collectors.groupingBy(IdAddonRuleEntity::getAddonGoodsCode)) : new HashMap<>();
        // 查询可能加价信息
        Map<String, List<IdAddonRuleEntity>> willAddOn = paidGoodsCodeMapping.containsKey(0) ? idAddonRuleService.list(new LambdaQueryWrapper<IdAddonRuleEntity>().in(IdAddonRuleEntity::getTriggerGoodsCode, paidGoodsCodeMapping.get(0))).stream().collect(Collectors.groupingBy(IdAddonRuleEntity::getTriggerGoodsCode)) : new HashMap<>();
        orderQueryResponseVo.getOrderGoods().forEach(t -> {
            if(giftRulesMapping.containsKey(t.getGoodsCode())){
                t.setGiftInfo(giftRulesMapping.get(t.getGoodsCode()));
            }
            if (realAddOn.containsKey(t.getGoodsCode())) {
                List<Integer> addOnPriceList = realAddOn.get(t.getGoodsCode()).stream().map(IdAddonRuleEntity::getAddonPrice).collect(Collectors.toList());
                addOnPriceList.add(t.getGoodsPrice());
                //最低价格
                t.setGoodsPrice(addOnPriceList.stream().min(Integer::compareTo).get());
            }
            if(willAddOn.containsKey(t.getGoodsCode())){
                t.setAddonInfo(willAddOn.get(t.getGoodsCode()));
            }
        });
        return orderQueryResponseVo.getOrderGoods();
    }

    /**
     * 分佣
     *
     * @param amount 订单金额
     * @param userId 用户id
     */
    private void distributeInvitation(Integer amount, Integer userId) {
        if (amount == 0) {
            log.info("订单金额0，不进行分佣");
            return;
        }
        UserEntity byId = userService.getById(userId);
        if (byId.getInvitationId() != 0) {
            BigDecimal multiply = new BigDecimal(amount).multiply(new BigDecimal(invitationDistributePercentage));
            userWalletService.update(new LambdaUpdateWrapper<UserWalletEntity>().eq(UserWalletEntity::getUserId, byId.getInvitationId()).setSql("total_amount = total_amount +" + Math.round(multiply.doubleValue())));
            UserWalletEntity invitationUserWallet = userWalletService.getOne(new LambdaQueryWrapper<UserWalletEntity>().eq(UserWalletEntity::getUserId, byId.getInvitationId()));
            // 更新邀请人钱包数据
            userWalletService.parseWalletVo(invitationUserWallet);
            boolean save = walletHistoryService.save(new WalletHistoryEntity().setAmount(multiply.toString()).setTransactionId("-").setUserId(byId.getInvitationId()).setContent("用户[" + byId.getInvitationId() + "]邀请用户[" + userId + "]付费奖励").setWalletType(WalletTypeEnum.USER).setWalletId(invitationUserWallet.getId()));
            if (save) {
                log.info("用户{}邀请人{}分佣成功", userId, byId.getInvitationId());
            } else {
                log.error("用户{}邀请人{}分佣失败", userId, byId.getInvitationId());
            }
        } else {
            log.debug("用户{}没有邀请人, 订单无需分佣", userId);
        }
    }
}

